package com.qfmy.web.app.service.impl.conmon;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.qfmy.model.entity.novel.Novel;
import com.qfmy.web.app.mapper.novel.NovelMapper;
import com.qfmy.web.app.service.conmon.FileUploadService;
import com.qfmy.web.app.service.conmon.NovelCommonService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 小说海报生成实现（仅修改海报生成逻辑，复用已有MinIO上传方法）
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class NovelCommonServiceImpl implements NovelCommonService {

    /** 常量配置 */
    private static final int POSTER_WIDTH = 600;
    private static final int POSTER_HEIGHT = 900;
    private static final int QR_CODE_SIZE = 150;
    private static final String FONT_NAME = "SimHei";
    private static final int IMAGE_LOAD_TIMEOUT = 5000;

    /**
     * 小说Mapper
     */
    @Resource
    private NovelMapper novelMapper;

    /**
     * 注入文件上传
     */
    @Autowired
    private FileUploadService fileUploadService;

    /**
     * Redis缓存
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 生成小说海报（核心修改：生成后调用已有upload方法上传，返回URL）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generatePoster(Integer novelId) {
        String redisKey = "app:poster:" + novelId;
        // 缓存存在直接返回URL
        if (redisTemplate.hasKey(redisKey)) {
            return redisTemplate.opsForValue().get(redisKey);
        }

        try {
            // 查询小说信息
            Novel novel = novelMapper.selectById(novelId);
            if (novel == null) {
                log.error("生成海报失败：小说ID={}不存在", novelId);
                return "";
            }

            // 数据库已有海报URL，直接返回
            String existingPosterUrl = novel.getPoster();
            if (existingPosterUrl != null && !existingPosterUrl.trim().isEmpty()) {
                redisTemplate.opsForValue().set(redisKey, existingPosterUrl, 3, TimeUnit.DAYS);
                return existingPosterUrl;
            }

            // 1. 生成海报图片（BufferedImage）
            BufferedImage posterImage = createPosterImage(novel);

            // 2. 将BufferedImage转为MultipartFile（用于调用upload方法）
            MultipartFile posterFile = convertToMultipartFile(posterImage, novelId);

            // 3. 调用已有upload方法上传到服务器（复用您实现的MinIO上传逻辑）
            String posterUrl = fileUploadService.upload(posterFile);
            if (posterUrl == null || posterUrl.trim().isEmpty()) {
                log.error("海报上传失败，小说ID={}", novelId);
                return "";
            }

            // 4. 更新数据库海报URL
            novel.setPoster(posterUrl);
            novelMapper.updateByNovel(posterUrl,novelId);

            // 5. 缓存海报URL
            redisTemplate.opsForValue().set(redisKey, posterUrl, 3, TimeUnit.DAYS);

            return posterUrl;

        } catch (Exception e) {
            log.error("生成海报异常，小说ID={}", novelId, e);
            return "";
        }
    }

    /**
     * 生成海报图片（核心绘制逻辑，保持不变）
     */
    private BufferedImage createPosterImage(Novel novel) throws WriterException {
        BufferedImage poster = new BufferedImage(POSTER_WIDTH, POSTER_HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = poster.createGraphics();
        // 抗锯齿设置
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 绘制背景
        drawBackground(g);
        // 绘制小说封面
        drawNovelCover(g, novel.getImage());
        // 绘制小说信息
        drawNovelInfo(g, novel);
        // 绘制二维码
        drawQrCode(g, novel.getNovelId());
        // 绘制底部信息
        drawFooter(g);

        g.dispose();
        return poster;
    }

    /**
     * 将BufferedImage转换为MultipartFile（适配upload方法参数）
     */
    private MultipartFile convertToMultipartFile(BufferedImage image, Integer novelId) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", bos); // 将 BufferedImage 写入字节流（PNG 格式）
        byte[] imageBytes = bos.toByteArray();

        // 生成唯一文件名（示例格式：20251006/novel_poster_123_xxxxxx.png）
        String fileName = new SimpleDateFormat("yyyyMMdd").format(new Date())
                + "/novel_poster_" + novelId + "_" + UUID.randomUUID() + ".png";

        // 封装为 MockMultipartFile
        InputStream inputStream = new ByteArrayInputStream(imageBytes);
        return new MockMultipartFile(
                "file",       // 表单字段名（与 upload 方法的接收字段一致）
                fileName,     // 文件名
                "image/png",  // MIME 类型（确保浏览器能直接预览）
                inputStream   // 图片字节流
        );
    }

    /**
     * 绘制海报
     * @param g
     */
    private void drawBackground(Graphics2D g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, POSTER_WIDTH, POSTER_HEIGHT);
    }

    /**
     * 绘制小说封面
     * @param g
     * @param imageUrl
     */
    private void drawNovelCover(Graphics2D g, String imageUrl) {
        if (imageUrl == null || imageUrl.trim().isEmpty()) {
            log.warn("小说封面URL为空，使用默认封面");
            drawDefaultCover(g);
            return;
        }

        String url = imageUrl.trim();
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            log.error("封面URL格式错误（非HTTP/HTTPS）：{}", url);
            drawDefaultCover(g);
            return;
        }

        HttpURLConnection connection = null;
        InputStream inputStream = null;
        try {
            URL coverUrl = new URL(url);
            connection = (HttpURLConnection) coverUrl.openConnection();
            connection.setConnectTimeout(IMAGE_LOAD_TIMEOUT);
            connection.setReadTimeout(IMAGE_LOAD_TIMEOUT);
            connection.setRequestMethod("GET");
            connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36");

            int responseCode = connection.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                log.error("封面URL响应失败，状态码={}，URL={}", responseCode, url);
                drawDefaultCover(g);
                return;
            }

            String contentType = connection.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                log.error("URL返回非图片类型，Content-Type={}，URL={}", contentType, url);
                drawDefaultCover(g);
                return;
            }

            inputStream = connection.getInputStream();
            BufferedImage coverImage = ImageIO.read(inputStream);
            if (coverImage == null) {
                log.error("图片流解析失败，URL={}", url);
                drawDefaultCover(g);
                return;
            }

            // 计算缩放尺寸（保持宽高比）
            int targetWidth = 400;
            int targetHeight = coverImage.getHeight() * targetWidth / coverImage.getWidth() - 30;
            int x = (POSTER_WIDTH - targetWidth) / 2;
            int y = 50;

            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(coverImage, x, y, targetWidth, targetHeight, null);

        } catch (Exception e) {
            log.error("加载远程封面异常，URL={}", url, e);
            drawDefaultCover(g);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.warn("关闭图片输入流失败", e);
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * 绘制默认封面
     * @param g
     */
    private void drawDefaultCover(Graphics2D g) {
        g.setColor(new Color(220, 220, 220));
        g.fillRect(100, 60, 400, 500);

        g.setColor(Color.GRAY);
        g.setFont(new Font(FONT_NAME, Font.PLAIN, 24));
        FontMetrics metrics = g.getFontMetrics();
        String text = "暂无封面";
        int textX = 100 + (400 - metrics.stringWidth(text)) / 2;
        int textY = 80 + (500 + metrics.getAscent()) / 2;
        g.drawString(text, textX, textY);
    }

    /**
     * 绘制小说信息
     * @param g
     * @param novel
     */
    private void drawNovelInfo(Graphics2D g, Novel novel) {
        // 绘制标题（支持换行）
        g.setColor(Color.BLACK);
        g.setFont(new Font(FONT_NAME, Font.BOLD, 32));
        drawMultilineText(g, novel.getNovelName(), 50, 620, 500, 40);

        // 绘制作者
        g.setFont(new Font(FONT_NAME, Font.PLAIN, 24));
        g.setColor(new Color(66, 66, 66));
        g.drawString("作者: " + (novel.getAuthorName() != null ? novel.getAuthorName() : "未知作者"), 50, 680);

        // 绘制类型
        g.drawString("类型: " + (novel.getCategoryName() != null ? novel.getCategoryName() : "未知类型"), 50, 720);
    }

    /**
     * 绘制二维码
     * @param g
     * @param novelId
     * @throws WriterException
     */
    private void drawQrCode(Graphics2D g, Integer novelId) throws WriterException {
        // 二维码内容：替换为你的小说详情页链接
        String content = "https://mp-57f421b8-7c0d-41a6-b5b9-58468c147cc2.cdn.bspapp.com/cloudstorage/eaeb8751-eac1-48ff-8f3e-aca791189700.apk";

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE);
        BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);

        // 绘制二维码（右下角）
        int x = POSTER_WIDTH - QR_CODE_SIZE - 50;
        int y = POSTER_HEIGHT - QR_CODE_SIZE - 80;
        g.drawImage(qrImage, x, y, QR_CODE_SIZE, QR_CODE_SIZE, null);

        // 扫码提示
        g.setFont(new Font(FONT_NAME, Font.PLAIN, 20));
        g.setColor(new Color(102, 102, 102));
        g.drawString("扫码下载应用", x + 10, y + QR_CODE_SIZE + 30);
    }

    /**
     * 绘制页脚
     * @param g
     */
    private void drawFooter(Graphics2D g) {
        g.setFont(new Font(FONT_NAME, Font.PLAIN, 16));
        g.setColor(new Color(153, 153, 153));
        g.drawString("© 2025 清风小说阅读平台 版权所有", 150, POSTER_HEIGHT - 20);
    }

    /**
     * 绘制多行文本
     * @param g
     * @param text
     * @param x
     * @param y
     * @param maxWidth
     * @param lineHeight
     */
    private void drawMultilineText(Graphics2D g, String text, int x, int y, int maxWidth, int lineHeight) {
        if (text == null || text.isEmpty()) {
            g.drawString("未知标题", x, y);
            return;
        }

        FontMetrics metrics = g.getFontMetrics();
        String[] words = text.split(" ");
        StringBuilder line = new StringBuilder();

        for (String word : words) {
            String testLine = line + word + " ";
            if (metrics.stringWidth(testLine) > maxWidth) {
                g.drawString(line.toString(), x, y);
                line = new StringBuilder(word + " ");
                y += lineHeight;
            } else {
                line = new StringBuilder(testLine);
            }
        }
        g.drawString(line.toString(), x, y);
    }
}